package com.hyts.rpclet.context;

import com.google.common.base.Preconditions;
import com.hyts.rpclet.annotation.RpcletBean;
import com.hyts.rpclet.annotation.RpcletMethod;
import com.hyts.rpclet.core.RpcletServerDispatcher;
import com.hyts.rpclet.execute.RpcletMethodInvoker;
import com.hyts.rpclet.util.SpringContextUtils;
import lombok.Getter;
import net.sf.cglib.reflect.FastClass;

import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.rpclet.context
 * author:Libo/Alex
 * create-date:2019-07-09 23:14
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于:
 */
public abstract class AbstractRpcletContext implements RpcletContext {


    @Getter
    private RpcletServerDispatcher rpcletServerDispatcher;

    /**
     * 构造器服务操作注册服务
     */
    public AbstractRpcletContext(){
        Map<String, Object>  dataMap = SpringContextUtils.getApplicationContext().getBeansWithAnnotation(RpcletBean.class);
        dataMap.forEach((k,v)->{
            register(v);
        });
        rpcletServerDispatcher = new RpcletServerDispatcher(this);
    }

    /**
     * 注册服务rpc
     * @param rpcInstance
     */
    @Override
    public void register(Object rpcInstance) {
        Preconditions.checkArgument(rpcInstance == null,"rpc实例服务对象不可以为空!");
        Class<?> clazzType = rpcInstance.getClass();
        FastClass fastClass = FastClass.create(clazzType);
        Method[] methods = clazzType.getDeclaredMethods();
        if(clazzType.isAnnotationPresent(RpcletBean.class)) {
            for (Method method : methods) {
                RpcletMethod rpcletMethod = method.getAnnotation(RpcletMethod.class);
                if (rpcletMethod != null) {
                    method.setAccessible(true);
                    add(clazzType.getName()+"."+method.getName(),RpcletMethodInvoker.builder().fastMethod(fastClass.getMethod(method))
                            .rpcletBean(rpcInstance)
                            .argumentTypeList(method.getParameterTypes()[0]).build());

                }
            }
        }
    }

    @Override
    public void unregister(String accessRpcUrl) {
        Preconditions.checkArgument(StringUtils.isEmpty(accessRpcUrl),"访问的url rpc服务不可以为空!");
        remove(accessRpcUrl);
    }



    /**
     * 新增服务对象
     */
    public abstract void add(String accessRpcUrl,RpcletMethodInvoker rpcletMethodInvoker);


    /**
     * 删除服务对象
     */
    public abstract void remove(String accessRpcUrl);

}
